<template>
  <div ref="container" class="container"
       :style="{'overflow-x':'hidden','overflow-y':expandScreen?'hidden':'auto',width:`${containerSize.width}px`,height:`${containerSize.height}px`}"
       @scroll="expandScreen?null:scrollToolBar()">
    <canvas ref="canvas" :class={brush:isDraw} :width="canvasSize.width" :height="canvasSize.height"
            @pointerdown="canvasMouseDown"/>

    <!-- 播放遮罩层 -->
    <mask-canvas v-if="isZoom && zoomImage" :zoomMultiples="zoomMultiples" :isDraw=false :containerSize="canvasSize"
                 :zoomLocation="zoomImage.location" :imageFile="zoomImage.url" :isZoom="isZoom"
                 @InflateRect="$emit('InflateRect',$event)"/>
  </div>
</template>
<script>
  // import { mapState, mapActions, mapGetters } from "vuex";
  // import action from "../../../common/typeActions";
  // import bus from "../../../common/bus";
  import SlideElement from './SlideElement'
  import MaskCanvas from './MaskCanvas'

  // let canvasContext = null;
  export default {
    name: 'SlidePictureViewer',
    props: {
      brushColor: {type: String, default: '#FF0000'},
      brushWidth: {type: Number, default: 4},
      drawMode: {type: String, default: 'FreeLine'},
      zoomMultiples: {type: Number, default: 100},
      imageFiles: {
        type: Array,
        default: function () {
          return []
        }
      },
      texts: {
        type: Array,
        default: function () {
          return []
        }
      },
      trajectorys: {
        type: Array,
        default: function () {
          return []
        }
      },
      zoomImage: {
        type: Object,
        default: function () {
          return null
        }
      },
      scroll: {type: Number, default: 0},
      isFill: {type: Boolean, default: false},
      containerSize: {
        type: Object,
        default: function () {
          return {width: 200, height: 400}
        }
      },
      expandScreen: {type: Boolean, default: true},
      isDraw: {type: Boolean, default: false},
      isZoom: {type: Boolean, default: false}
    },
    components: {
      'slide-element': SlideElement,
      'mask-canvas': MaskCanvas
    },
    data: function () {
      return {
        images: [],
        canvasContext: null,
        canvasSize: {width: 200, height: 400},
        trajectory: [] // 标注轨迹
      }
    },
    computed: {
      zoomRectangleSize: {
        get () {
          return {
            width: this.containerSize.width * 0.3,
            height: this.containerSize.width * 0.3
          }
        }
      }
    },
    mounted: function () {
      this.$eventBus.$on('keydown', this.useKeyboardScroll)
      this.init()
    },
    beforeDestroy: function () {
      this.canvasContext = null
      this.$eventBus.$off('keydown', this.useKeyboardScroll)
    },
    watch: {
      imageFiles: function (n, o) {
        this.init()
      },
      trajectorys: function (n, o) {
        this.trajectory = JSON.parse(JSON.stringify(n))
      },
      containerSize: function (n, o) {
        if (n && o && n.width != o.width && n.height != o.height) {
          this.init()
        }
      },
      scroll: function (n, o) {
        if (this.expandScreen) {
          let container = this.$refs.container
          if (container) container.scrollTop = this.containerSize.height * n
        }
      },
      trajectory: function (n, o) {
        if (o.length > n.length) {
          this.paintImage()
        } else {
          this.drawTrajectory(n)
        }
      },
      isZoom: function (n, o) {
        let img = null
        if (n) {
          let canvas = this.$refs.canvas
          if (canvas) img = canvas.toDataURL()
        }
        this.$emit('ZoomStateChanged', img)
      }
    },
    methods: {
      init: function () {
        this.$nextTick(async function () {
          try {
            let images = []
            let imageSize = []
            // 画布大小
            let canvasSize = {
              width: this.containerSize.width,
              height: 0
            }
            // 加载初始化图片对象
            for (let i = 0; i < this.imageFiles.length; i++) {
              let img = await loadImage(
                this.imageFiles[i],
                this.containerSize,
                this.isFill,
                this.expandScreen
              )
              canvasSize.height += img.image.height
              images.push(img.image)
              imageSize.push({
                id: img.id,
                width: img.width,
                height: img.height
              })
            }
            canvasSize.height =
              canvasSize.height > this.containerSize.height
                ? canvasSize.height
                : this.containerSize.height
            this.images = images
            this.canvasSize = canvasSize
            this.$nextTick(function () {
              this.scrollToolBar(this.containerSize.height * this.scroll)
            })
            if (!this.expandScreen) this.$emit('ImageLoaded', imageSize)
            this.paintImage()
          } catch (error) {
          }
        })
      },
      scrollToolBar: function (scrollTop) {
        let container = this.$refs.container
        if (!container) return
        if (typeof scrollTop === 'number') {
          container.scrollTop = scrollTop
        } else {
          this.$emit('scroll', container.scrollTop / container.offsetHeight)
        }
      },
      useMouseMove: function () {
        let self = this
        let container = self.$refs.container
        if (!container) return
        let location = event.clientY

        container.onmousemove = () => {
          if (location > event.clientY) {
            container.scrollTop += location - event.clientY
          } else if (location < event.clientY) {
            container.scrollTop -= event.clientY - location
          }
          location = event.clientY
        }
        container.onmouseup = () => {
          container.onmouseup = container.onmousemove = null
        }
        container.onmouseout = () => {
          container.onmouseout = container.onmousemove = null
        }
      },
      useKeyboardScroll: function () {
        let container = this.$refs.container
        if (!container || (event.keyCode !== 33 && event.keyCode != 34)) return

        container.scrollTop += event.keyCode === 33 ? -10 : 10
      },
      // 获取标注轨迹
      canvasMouseDown: function () {
        let self = this
        if (!this.isDraw) return
        let canvas = this.$refs.canvas
        if (!canvas) return
        let startLoc = {x: event.offsetX, y: event.offsetY}
        let locs = {
          type: this.drawMode,
          location: [{
            x: startLoc.x / canvas.offsetWidth,
            y: startLoc.y / canvas.offsetHeight
          }],
          isDraw: true
        }
        this.trajectory.push(locs)
        canvas.onpointermove = function () {
          // 获取鼠标位置坐标
          switch (locs.type) {
            case 'FreeLine':
              locs.location.push({
                x: event.offsetX / canvas.offsetWidth,
                y: event.offsetY / canvas.offsetHeight
              })
              break
            case 'StraightLine':
              locs.location[1] = {
                x: event.offsetX / canvas.offsetWidth,
                y: event.offsetY / canvas.offsetHeight
              }
              break
            case 'Rectangle':
              locs.location[0].w = (event.offsetX - startLoc.x) / canvas.offsetWidth
              locs.location[0].h = (event.offsetY - startLoc.y) / canvas.offsetHeight
              break
          }
          // locs.push({
          //   x: event.offsetX / canvas.offsetWidth,
          //   y: event.offsetY / canvas.offsetHeight
          // });
        }
        canvas.onpointerup = () => {
          canvas.onpointerup = canvas.onpointermove = null
          self.$emit('DrawTrajectoryed', this.trajectory)
        }
        canvas.onpointerout = () => {
          canvas.onpointerout = canvas.onpointermove = null
          self.$emit('DrawTrajectoryed', this.trajectory)
        }
      },
      // 绘制文字
      paintText: function () {
        let self = this
        if (!this.canvasContext) return
        this.texts.forEach(item => {
          this.canvasContext.font = 'normal normal bold 65px Microsoft YaHei'
          // this.canvasContext.fillStyle = "rgb(55, 96, 146)";
          this.canvasContext.fillStyle = '#FFFFFF'
          this.canvasContext.textAlign = item.textAlign
          this.canvasContext.fillText(
            item.text,
            self.canvasSize.width * item.width,
            self.containerSize.height * item.height
          )
        })
      },
      // 绘制图片
      paintImage: function () {
        this.$nextTick(function () {
          let canvas = this.$refs.canvas
          if (!this.canvasContext) {
            this.canvasContext = canvas.getContext('2d')
          } else {
            this.canvasContext.clearRect(
              0,
              0,
              this.canvasSize.width,
              this.canvasSize.height
              // canvas.offsetWidth,
              // canvas.offsetHeight
            )
          }
          let top = 0
          this.images.forEach(item => {
            // 将图片绘制到画布上
            this.canvasContext.drawImage(
              item,
              (this.canvasSize.width - item.width) / 2,
              top,
              item.width,
              item.height
            )
            top += item.height
          })
          this.paintText()
          this.trajectory = JSON.parse(JSON.stringify(this.trajectorys))
        })
      },
      // 绘制标注轨迹
      drawTrajectory: function (trajectory) {
        let canvas = this.$refs.canvas
        if (!canvas) return
        if (!this.canvasContext) {
          // 创建上下文
          this.canvasContext = canvas.getContext('2d')
        } else {
          // 清空画布内容
          this.canvasContext.clearRect(
            0,
            0,
            canvas.offsetWidth,
            canvas.offsetHeight
          )
        }
        // this.paintImage();

        this.$nextTick(function () {
          // 设置画笔颜色、宽度
          this.canvasContext.strokeStyle = this.brushColor
          this.canvasContext.lineWidth = this.brushWidth
          trajectory.forEach(item => {
            // 绘制自由线条
            // if (item.isDraw) {
            if (item.type == 'Rectangle') {
              this.drawRectangle(canvas, item.location)
            } else if (item.type == 'Ellipse') {
              this.drawEllipse(canvas, item.location)
            } else {
              this.drawFreeLine(canvas, item.location)
            }
            // }
          })
        })
      },
      // 绘制自由线条
      drawFreeLine: function (canvas, locations) {
        if (!this.canvasContext || !canvas || !locations.length) return
        this.canvasContext.beginPath()
        locations.forEach(item => {
          let loc = {
            x: item.x * canvas.offsetWidth,
            y: item.y * canvas.offsetHeight
          }
          this.canvasContext.lineTo(loc.x, loc.y)
          this.canvasContext.moveTo(loc.x, loc.y)
        })
        this.canvasContext.closePath()
        this.canvasContext.stroke()
      },
      drawRectangle: function (canvas, locations) {
        if (!this.canvasContext || !canvas || !locations.length) return
        this.canvasContext.beginPath()
        locations.forEach(item => {
          let loc = {
            x: item.x * canvas.offsetWidth,
            y: item.y * canvas.offsetHeight,
            w: item.w * canvas.offsetWidth,
            h: item.h * canvas.offsetHeight
          }
          this.canvasContext.rect(loc.x, loc.y, loc.w, loc.h)
        })
        this.canvasContext.closePath()
        this.canvasContext.stroke()
      }
    }
  }

  /** @augments 加载图片对象 */
  function loadImage (img, containerSize, isFill, isExpandScreen) {
    return new Promise((resolve, reject) => {
      let result = {id: img.id}
      let image = new Image()
      image.src = img.url
      image.onload = function () {
        if (isFill) {
          image.width = containerSize.width
          image.height = containerSize.height
        } else if (
          image.width < containerSize.width &&
          image.height < containerSize.height
        ) {
          // else if (isExpandScreen) {
          //     image.width = containerSize.width * img.width;
          //     image.height = containerSize.height * img.height;
          // }
          // 当图片比图片框小时不做任何改变
          image.width = image.width
          image.height = image.height
        } else if (
          containerSize.width / containerSize.height <=
          image.width / image.height
        ) {
          // 原图片宽高比例 大于 图片框宽高比例
          image.width = containerSize.width
          // 以框的宽度为标准
          image.height = containerSize.width * (image.height / image.width)
        } else {
          // 原图片宽高比例 小于 图片框宽高比例
          image.width = containerSize.height * (image.width / image.height)
          // 以框的高度为标准
          image.height = containerSize.height
        }

        result.width = image.width / containerSize.width
        result.height = image.height / containerSize.height
        result.image = image
        resolve(result)
      }
    })
  }
</script>
<style>
  .container {
    z-index: 400;
    position: absolute;
    background-color: #fefefe;
    /* background-color:transparent; */
  }

  .container .brush {
    cursor: url("~@/assets/img/SlideEditor/brush.png"), auto;
  }

  .container canvas {
    letter-pacing: 5px;
  }

  .container::-webkit-scrollbar-thumb {
    background-color: #267abb;
    border-radius: 4px;
  }

  .container::-webkit-scrollbar {
    width: 8px;
    height: 8px;
    background: #cbe2ee;
  }
</style>
